///////////////////////////////////////////////////////////////////////////////////////////////////
// A9Codec_zxtune.h
// Codec for different ZX Spectrum formats
// Uses ZXTune library by Vitamin/CAIG (http://zxtune.googlecode.com)
// Needs: zxtune.lib linked (check pragma path from .cpp)
// Needs: include additional directories up to zxtune.h (in project settings)
// A minimal requirement would be zxtune.h, zxtune.lib
///////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef __A9CODEC_ZXTUNE_H__
#define __A9CODEC_ZXTUNE_H__

#include "zxtune.h"
#include "A9Codec.h"
#include <algorithm>
#include <map>
#include <string>

class a9Codec_zxtune : public a9Codec
{
public:
					a9Codec_zxtune();
virtual				~a9Codec_zxtune();
static	int			Init();
static	int			Done();

virtual	int			Open( char* name );
virtual	int			BeginRender( int pos, int loop );
virtual int			Render( byte* buffer, int size );
virtual	int			EndRender();
virtual	int			Close();

private:
	static ZXTuneHandle OpenModule(char* name);
private:
    template<class HandleType, class DtorRetType = void>
    class AutoHandle
    {
    public:
      AutoHandle()
        : Handle()
        , Dtor()
      {
      }

      AutoHandle(HandleType handle, DtorRetType (*dtor)(HandleType))
        : Handle(handle)
        , Dtor(dtor)
      {
      }

      AutoHandle(AutoHandle& rh)
        : Dtor(rh.Dtor)
      {
        std::swap(Handle, rh.Handle);
      }

      AutoHandle& operator = (AutoHandle& rh)
      {
        Reset();
        Dtor = rh.Dtor;
        std::swap(Handle, rh.Handle);
        return *this;
      }

      ~AutoHandle()
      {
        Reset();
      }

      void Reset()
      {
        if (Handle)
        {
          Dtor(Handle);
          Handle = 0;
        }
      }

      HandleType Get() const
      {
        return Handle;
      }

	  HandleType Release()
	  {
	    HandleType ret = 0;
		std::swap(ret, Handle);
		return ret;
	  }
    private:
      HandleType Handle;
      DtorRetType (*Dtor)(HandleType);
    };

    AutoHandle<ZXTuneHandle> Player;
	typedef std::map<std::string, ZXTuneHandle> NameToHandle;
	static NameToHandle CachedModules;
};

#endif
///////////////////////////////////////////////////////////////////////////////////////////////////
